﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;

using jade.core;
using jade.core.behaviours;
using jade.lang.acl;
using Newtonsoft.Json;

namespace CMS1 {
    public class Communicator : Agent {
        //public const int CHOOSE_OFFER = 2003;
        public const int INVITATION_RESULT = 2000;
        public const int DEALING_RESULT = 2001;
        public const int STATE_DETAILS = 2002;

        public const int DEALING_ISSUE = 2003;

        public DatabaseWrapper db {
            get;
            set;
        }

        public int residenceMessages = 0;
        public int caterMessages = 0;

        public bool responsesTimeOut;
        HandleDeals handleDealsBehaviour;

        public int ResidenceMessages {
            get;
            set;
        }
        public int CaterMessages {
            get;
            set;
        }

        public override void setup() {
            db = new DatabaseWrapper();
            db.initConnection(DatabaseWrapper.connString);
            addBehaviour(new ReceiveInternalMsgs());
            Timeout = 1000 * 60 * 60 * 24 * 2;
        }
        public long Timeout {
            get;
            set;
        }
        public void sendOutgoingMessages(int[] messagesIDs) {
            try {
            } catch (Exception ex) {
                System.Diagnostics.Debug.WriteLine(ex.Message + "  " + ex.InnerException);
            }
            /*
            MailMessage myMail = new MailMessage();
            myMail.From = "from@microsoft.com";
            myMail.To = "to@microsoft.com";
            myMail.Subject = "UtilMailMessage001";
            myMail.Priority = MailPriority.Low;
            myMail.BodyFormat = MailFormat.Html;
            myMail.Body = "<html><body>UtilMailMessage001 - success</body></html>";
            MailAttachment myAttachment = new MailAttachment("c:\attach\attach1.txt", MailEncoding.Base64);
            myMail.Attachments.Add(myAttachment);
            SmtpMail.SmtpServer = "MyMailServer";
            SmtpMail.Send(myMail);
             */

            /*
            string to = "jane@contoso.com";
            string from = "ben@contoso.com";
            MailMessage message = new MailMessage(from, to);
            message.Subject = "Using the new SMTP client.";
            message.Body = @"Using this new feature, you can send an e-mail message from an application very easily.";
             */

            //string msgsIDsGroup = "'" + String.Join("','", messagesIDs) + "'";
            /*foreach (string id in messagesIDs)
            {
                msgsIDsGroup += "'" + id + "',";
            }
            msgsIDsGroup = msgsIDsGroup.Substring(0, msgsIDsGroup.Length - 1);*/

            string msgsIDsGroup = "";
            for (int i = 0; i < messagesIDs.Length - 1; i++) {
                msgsIDsGroup += messagesIDs[i] + "','";
            }
            System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
            message.From = new System.Net.Mail.MailAddress("mas-cm@live.com");
            System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.live.com");
            smtp.EnableSsl = true;
            smtp.Credentials = new System.Net.NetworkCredential("mas-cm@live.com", "it-can-be");
            object[][] rows = (object[][])db.select("name, email, subject, message_content").from("Outgoing_message, Recipient").
                where("Recipient.outgoing_message_id in (" + msgsIDsGroup + ")").execute();
            if (rows == null) {
                throw new InvalidOperationException("Sending Outgoing message(s): " + msgsIDsGroup + " with no associated Recipients!!");
            }
            bool runDealingBehaviour = false;
            foreach (object[] row in rows) {
                message.To.Add((string)row[1]);
                message.Subject = (string)row[2];//"Blah " + DateTime.Now.ToShortTimeString();
                string body = (string)row[3];// "This is the message body";
                message.Body = body.Replace("{recipient_name}", (string)row[0]);
                if (body.Contains("{residence_accept_link}")) {
                    ResidenceMessages++;
                    message.Body = message.Body.Replace("{residence_accept_link}", "http://link.com");
                    runDealingBehaviour = true;
                } else if (body.Contains("{cater_accept_link}")) {
                    CaterMessages++;
                    message.Body = message.Body.Replace("{cater_accept_link}", "http://link.com");
                    runDealingBehaviour = true;
                }
                smtp.Send(message);
            }
            if (runDealingBehaviour) {
                handleDealsBehaviour = new HandleDeals(this);
                addBehaviour(handleDealsBehaviour);
                addBehaviour(new ResponsesTimeOut(this, Timeout));
            }
        }
        public void sendInformEmails(string[] emails, string messageBody) {
            System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
            message.From = new System.Net.Mail.MailAddress("mas-cm@live.com");
            System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.live.com");
            smtp.EnableSsl = true;
            smtp.Credentials = new System.Net.NetworkCredential("mas-cm@live.com", "it-can-be");

            foreach (string email in emails) {
                message.To.Add(email);
            }
            message.Subject = "No offer accepted";//"Blah " + DateTime.Now.ToShortTimeString();
            message.Body = messageBody;
            smtp.Send(message);
        }
        public void sendOfferAcceptanceEmail(string[] emails, string messageBody) {
            System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
            message.From = new System.Net.Mail.MailAddress("mas-cm@live.com");
            System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.live.com");
            smtp.EnableSsl = true;
            smtp.Credentials = new System.Net.NetworkCredential("mas-cm@live.com", "it-can-be");

            foreach (string email in emails) {
                message.To.Add(email);
            }
            message.Subject = "Offer Accepted";//"Blah " + DateTime.Now.ToShortTimeString();
            message.Body = messageBody;
            smtp.Send(message);
        }
        public void sendRejectEmailsToHotels(string[] emails) {
            System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
            message.From = new System.Net.Mail.MailAddress("mas-cm@live.com");
            System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.live.com");
            smtp.EnableSsl = true;
            smtp.Credentials = new System.Net.NetworkCredential("mas-cm@live.com", "it-can-be");

            foreach (string email in emails) {
                message.To.Add(email);
            }
            message.Subject = "Informing about Offer";//"Blah " + DateTime.Now.ToShortTimeString();
            message.Body = "We have accepted an offer from another candidate hotel, thanks for your co-operation.";
            smtp.Send(message);
        }
        public void sendRejectEmailsToCaterProviders(string[] emails) {
            System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
            message.From = new System.Net.Mail.MailAddress("mas-cm@live.com");
            System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.live.com");
            smtp.EnableSsl = true;
            smtp.Credentials = new System.Net.NetworkCredential("mas-cm@live.com", "it-can-be");

            foreach (string email in emails) {
                message.To.Add(email);
            }
            message.Subject = "Informing about Offer";//"Blah " + DateTime.Now.ToShortTimeString();
            message.Body = "We have accepted an offer from another candidate cater provider, thanks for your co-operation.";
            smtp.Send(message);
        }
        public void sendReductionRequestEmail(string email,int totalCost, int reductionAmount, string currency) {
            System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
            message.From = new System.Net.Mail.MailAddress("mas-cm@live.com");
            System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.live.com");
            smtp.EnableSsl = true;
            smtp.Credentials = new System.Net.NetworkCredential("mas-cm@live.com", "it-can-be");

            message.To.Add(email);
            message.Subject = "Price decrease request";//"Blah " + DateTime.Now.ToShortTimeString();
            message.Body = "We have a shortage in our budget and we would like you to decrease the total cost: "+totalCost+" of your service by: "
                + reductionAmount + " " + currency +
                "http://Accept decrease request        http://Refuse";// "This is the message body";
            smtp.Send(message);
        }

        public void sendReductionCancellationEmail(string email) {
            System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
            message.From = new System.Net.Mail.MailAddress("mas-cm@live.com");
            System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.live.com");
            smtp.EnableSsl = true;
            smtp.Credentials = new System.Net.NetworkCredential("mas-cm@live.com", "it-can-be");

            message.To.Add(email);
            message.Subject = "About the price decrease request";//"Blah " + DateTime.Now.ToShortTimeString();
            message.Body = "Appearantly we managed to solve our budget shortage issue and so we accept your first offer." +
                "\n Appologize for the inconvience and thanks for your co-operation.";
            smtp.Send(message);
        }

        /*************************************************
         * 
         * **********************************************/
        class ResponsesTimeOut : WakerBehaviour {
            public ResponsesTimeOut(Agent agent, long timeout)
                : base(agent, timeout) {
            }
            public override void onWake() {
                base.onWake();
                ((Communicator)myAgent).responsesTimeOut = true;
                ((Communicator)myAgent).handleDealsBehaviour.restart();
                ((Communicator)myAgent).removeBehaviour(this);
            }
        }


        /*************************************************
         * Receive Internal
         * **********************************************/
        class ReceiveInternalMsgs : CyclicBehaviour {
            MessageTemplate internalMsg;
            DatabaseWrapper db;

            public ReceiveInternalMsgs() {
                MessageTemplate fromScheduler = MessageTemplate.MatchSender(new AID("Scheduler", AID.ISLOCALNAME));
                MessageTemplate fromNegotiator = MessageTemplate.MatchSender(new AID("Negotiator", AID.ISLOCALNAME));
                //MessageTemplate fromMonitor = MessageTemplate.MatchSender(new AID("Monitor", AID.ISLOCALNAME));
                internalMsg = MessageTemplate.or(fromScheduler, fromNegotiator);
                db = ((Communicator)myAgent).db;
            }
            public override void action() {
                ACLMessage aclMsg = myAgent.receive(internalMsg);
                if (aclMsg != null) {
                    ACLMessage reply;
                    Message msg = JsonConvert.DeserializeObject<Message>(aclMsg.getContent());
                    switch (msg.Purpose) {
                        case Scheduler.SCHEDULED_OUTGOING_MESSAGE:
                            //string[] messagesIDs = aclMsg.getContent().Substring(5).Split(',');
                            ((Communicator)myAgent).sendOutgoingMessages(JsonConvert.DeserializeObject<int[]>(msg.Data));
                            break;
                        /*case Reporter.COMPLETE_STATE_DETAILS:
                            msg.Purpose = STATE_DETAILS;
                            string[] stateDetails = new string[2];
                            stateDetails[0] = getInvitationDetails();
                            stateDetails[1] = getDealingResult();
                            msg.Data = JsonConvert.SerializeObject(stateDetails);
                            reply = aclMsg.createReply();
                            reply.setContent(JsonConvert.SerializeObject(msg));
                            myAgent.send(reply);
                            break;*/
                        case INVITATION_RESULT:
                            msg.Data = getInvitationDetails();
                            reply = aclMsg.createReply();
                            reply.setContent(JsonConvert.SerializeObject(msg));
                            myAgent.send(reply);
                            break;
                        case DEALING_RESULT:
                            msg.Data = getDealingResult();
                            reply = aclMsg.createReply();
                            reply.setContent(JsonConvert.SerializeObject(msg));
                            myAgent.send(reply);
                            break;
                        case INVITATION_RESULT | Scheduler.PHASE_TRANSMISSION:
                            msg.Data = JsonConvert.SerializeObject(new string[] { msg.Data, getInvitationDetails() });
                            reply = aclMsg.createReply();
                            reply.setContent(JsonConvert.SerializeObject(msg));
                            myAgent.send(reply);
                            break;
                        case DEALING_RESULT | Scheduler.PHASE_TRANSMISSION:
                            msg.Data = JsonConvert.SerializeObject(new string[] { msg.Data, getDealingResult() });
                            reply = aclMsg.createReply();
                            reply.setContent(JsonConvert.SerializeObject(msg));
                            myAgent.send(reply);
                            break;
                    }
                } else {
                    block();
                }
            }

            private string getDealingResult() {
                DealingOutcome dealingResult = ((Communicator)myAgent).handleDealsBehaviour.getDealingOutcome();
                return JsonConvert.SerializeObject(dealingResult);
            }

            private string getInvitationDetails() {
                InvitationOutcome invitationOutcome = new InvitationOutcome();
                // target person or service
                object[][] results = (object[][])db.select("name, response_status").from("Recipient, Outgoing_message").
                    where("outgoing_message_id=Outgoing_message.id and (target='personal' or target='service'").and(GatewayAgent.myConf).execute();
                foreach (object[] result in results) {
                    if ((int)result[1] == 1) {
                        invitationOutcome.Accepted.Add((string)result[0]);
                    } else if ((int)result[1] == -1) {
                        invitationOutcome.Rejected.Add((string)result[0]);
                    } else if ((int)result[1] == 0) {
                        invitationOutcome.NoResponse.Add((string)result[0]);
                    }
                }
                return JsonConvert.SerializeObject(invitationOutcome);
            }
        }
        /*************************************************
         * Receive External
         * **********************************************
        class ReceiveExternalMsgs : CyclicBehaviour {
            MessageTemplate externalMsg;
            DatabaseWrapper db;

            public ReceiveExternalMsgs() {
                externalMsg = MessageTemplate.MatchSender(new AID("GatewayAgent", AID.ISLOCALNAME));
                db = ((Communicator)myAgent).db;
            }
            public override void action() {
                ACLMessage msg = myAgent.receive(externalMsg);
                if (msg != null) {
                    int purpose = Convert.ToInt32(msg.getContent().Substring(0, 4));
                    switch (purpose) {
                        case MESSAGE_RESPONSE:
                            break;
                    }
                } else {
                    block();
                }
            }
        }*/

    }
}

/*    Gmail......
try
{
    System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
    message.To.Add("mohamed-elhadi@live.com");
    message.Subject = "Blah " + DateTime.Now.ToShortTimeString();
    message.From = new System.Net.Mail.MailAddress("mohamed.elhadi.g@gmail.com");
    message.Body = "This is the message body";
    System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.gmail.com");
    smtp.EnableSsl = true;
    smtp.Credentials = new System.Net.NetworkCredential("mohamed.elhadi.g@gmail.com", "ziadgb-ad");
    smtp.Send(message);
}
catch (Exception ex)
{
    System.Diagnostics.Debug.WriteLine(ex.Message + "  " + ex.InnerException);
}*/



/*try
{
    System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
    message.To.Add("mohamed-elhadi@live.com");
    message.Subject = "Blah";
    message.From = new System.Net.Mail.MailAddress("From@online.microsoft.com");
    message.Body = "This is the message body";
    System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.live.com");
    smtp.EnableSsl = true;
    smtp.Credentials = new System.Net.NetworkCredential("confmanagement@live.com", "it-can-be");
    smtp.Send(message);
}
catch (Exception ex)
{
    System.Diagnostics.Debug.WriteLine(ex.Message + "  " + ex.InnerException);
}*/